import {Component, OnDestroy, OnInit, TemplateRef, ViewChild} from '@angular/core';
import {MessageSocketService} from '../../service/message-socket.service';
import {MessageBody} from '../../model/message-body';
import {CommonParams, MessageParams} from '../../../utils/common-params';
import {DrawLotsModel} from '../../model/draw-lots.model';
import {MyStorageService} from '../../../utils/my.storage.service';
import {Router} from '@angular/router';
import {ConstantsService} from '../../../utils/constants.service';
import {WebSocketSubject} from 'rxjs/internal-compatibility';
import {ApiService} from '../../../utils/api.service';
import {Response} from '../../../utils/response';
import {NzModalService} from 'ng-zorro-antd/modal';
import {NzNotificationService} from 'ng-zorro-antd/notification';

@Component({
  selector: 'app-draw-lots',
  templateUrl: './draw-lots.component.html',
  styleUrls: ['./draw-lots.component.less']
})
export class DrawLotsComponent implements OnInit, OnDestroy {
  userName;
  choosePositions = CommonParams.POSITIONS;
  positions = [];
  resultPositions: DrawLotsModel[] = [];
  currentBrothers: DrawLotsModel[] = [];
  isPrepared = false;
  isDispatch = false;
  isDestroy = false;
  me;
  gameId;
  socketSubject$: WebSocketSubject<MessageBody>;
  @ViewChild('notificationTemplate', {static: true})
  notificationTemplate: TemplateRef<{}>;
  notificationMessage: string;
  notificationType = 1; // 通知类型，1：加入，2：离开 3：状态变更 4：比赛结果（赢） 5：比赛结果（输） 6：比赛结果（取消）
  constructor(private messageSocketService: MessageSocketService, private storage: MyStorageService, private router: Router,
              private constants: ConstantsService, private api: ApiService, private modalService: NzModalService,
              private notification: NzNotificationService) {
    this.me = Number.parseInt(this.storage.get(CommonParams.userIdName), 10);
    this.userName = this.storage.get(CommonParams.userName);
  }

  logout() {
    this.storage.setObject(CommonParams.loginUserName,
      Object.assign(this.storage.getObject(CommonParams.loginUserName), {password: ''}));
    this.storage.delete(CommonParams.tokenName);
    this.storage.delete(CommonParams.userIdName);
    this.storage.delete(CommonParams.userName);
    this.messageSocketService.close();
    this.router.navigate(['login']).then();
  }

  ngOnDestroy(): void {
    this.messageSocketService.close();
    this.isDestroy = true;
  }

  ngOnInit(): void {
    this.getIfLastGameNotFinish().then(() => {
      this.createConnection();
    });
  }

  /**
   * 建立连接
   */
  createConnection() {
    this.socketSubject$ = this.messageSocketService.open(this.me);
    this.socketSubject$.subscribe((message: MessageBody) => {
      switch (message.type) {
        case MessageParams.MESSAGE_TYPE.join: // 有人加入
          this.currentBrothers = message.body.brothers;
          if (message.body.brotherId !== this.me) {
            this.notice(message.body.message, 1);
          }
          break;
        case MessageParams.MESSAGE_TYPE.leave: // 有人离开
          this.currentBrothers = message.body.brothers;
          this.notice(message.body.message, 2);
          break;
        case MessageParams.MESSAGE_TYPE.prepare: // 准备
          this.currentBrothers = message.body;
          break;
        case MessageParams.MESSAGE_TYPE.cancelPrepare: // 取消准备
          this.currentBrothers = message.body;
          break;
        case MessageParams.MESSAGE_TYPE.distribution: // 分配位置
          this.resultPositions = message.body;
          this.isDispatch = true;
          for (let i = 0; i < this.resultPositions.length; i++) {
            if (this.resultPositions[i]) {
              this.gameId = this.resultPositions[i].gameId;
            }
          }
          break;
        case MessageParams.MESSAGE_TYPE.gameResult: // 游戏结果
          this.gameResultChange(Number.parseInt(message.body.win, 10), message.body.message, message.body.brotherId);
          break;
        case MessageParams.MESSAGE_TYPE.kickOut: // 踢下线
          this.messageSocketService.close();
          this.router.navigate(['login']).then();
          break;
        case MessageParams.MESSAGE_TYPE.offline: // 离线
          this.messageSocketService.close();
          this.constants.error('您已退出');
          break;
        case MessageParams.MESSAGE_TYPE.error: // 服务端错误
          this.constants.error('服务端错误');
          this.createConnection();
          break;
      }
    }, error => {
      this.constants.error('socket异常，请查看服务器信息');
      if (!this.isDestroy) {
        this.createConnection();
      }
    });
  }

  notice(msg, type, duration?: number) {
    this.notificationMessage = msg;
    this.notificationType = type;
    this.notification.template(this.notificationTemplate, {nzDuration: duration || 1500});
  }

  /**
   * 按位置按钮
   * @param id 位置id
   */
  choose(id) {
    if (this.isPrepared) {
      return;
    }
    const index = this.positions.indexOf(id);
    if (index < 0) {
      this.positions.push(id);
    } else {
      this.positions.splice(index, 1);
    }
  }

  /**
   * 准备
   */
  prepare() {
    if (this.positions.length <= 0) {
      this.constants.info('你还没选位置呢兄弟');
      return;
    }
    this.isPrepared = true;
    this.messageSocketService.send(new MessageBody({
      type: MessageParams.MESSAGE_TYPE.prepare,
      body: this.positions.sort()
    }).toParams());
  }

  /**
   * 取消准备
   */
  cancelPrepare() {
    this.isPrepared = false;
    this.messageSocketService.send(new MessageBody({
      type: MessageParams.MESSAGE_TYPE.cancelPrepare,
      body: []
    }).toParams());
  }

  /**
   * 获取是否还有未结束的比赛
   */
  getIfLastGameNotFinish() {
    return new Promise((resolve, reject) => {
      this.api.getIfLastGameNotFinish().subscribe((res: Response) => {
        if (res.data) {
          this.gameId = res.data.id;
          this.isPrepared = true;
          this.isDispatch = true;
          this.resultPositions = res.data.brothers;
        } else {
          this.isPrepared = false;
          this.isDispatch = false;
          this.resultPositions = [];
        }
        resolve(true);
      });
    });
  }

  /**
   * 提交比赛结果
   * @param win 结果
   */
  submitResult(win) {
    this.modalService.confirm({
      nzTitle: '',
      nzContent: '确认提交结果？',
      nzOnOk: () => {
        this.api.submitGame({id: this.gameId, win}).subscribe((res: Response) => {
          if (res.isSuccess) {
            this.messageSocketService.send(new MessageBody({
              type: MessageParams.MESSAGE_TYPE.gameResult,
              body: win.toFixed()
            }).toParams());
          } else {
            this.constants.info(res.msg);
            this.getIfLastGameNotFinish().then();
          }
        });
      }
    });
  }

  /**
   * 有人修改了比赛结果
   * @param win 结果
   * @param message 消息
   * @param brotherId 提交者id
   */
  gameResultChange(win: number, message: string, brotherId: number) {
    if (this.me !== brotherId) {
      if (win === 1) {
        this.notice(message, 4, 2000);
      } else if (win === 2) {
        this.notice(message, 5, 2000);
      } else {
        this.notice(message, 6, 2000);
      }
    }
    this.isDispatch = false;
    this.cancelPrepare();
  }
}
